<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>记忆增强墙面系统 - 实时监控</title>
    <style>
        /* 基础样式 */
        * {
            box-sizing: border-box;
        }

        body {
            font-family: 'Segoe UI', sans-serif;
            background: linear-gradient(to bottom right, #e3f2fd, #f5f7fa);
            margin: 0;
            min-height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            padding: 1rem;
        }

        /* 容器样式 */
        .container {
            width: 100%;
            max-width: 1300px;
            background: white;
            border-radius: 2rem;
            overflow: hidden;
            box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15);
            transition: all 0.3s ease;
        }

        /* 头部样式 */
        .header {
            background: linear-gradient(135deg, #1a73e8, #3f8efc);
            padding: 2.5rem;
            text-align: center;
            color: white;
            position: relative;
        }

        .header::after {
            content: '';
            position: absolute;
            bottom: -20px;
            left: 50%;
            transform: translateX(-50%);
            width: 60px;
            height: 4px;
            background: #fff;
            opacity: 0.3;
        }

        .header h1 {
            font-size: 2.8rem;
            font-weight: 700;
            margin-bottom: 0.8rem;
            letter-spacing: 1px;
        }

        .header p {
            font-size: 1.2rem;
            opacity: 0.95;
        }

        /* 网格布局 */
        .dashboard {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
            gap: 2rem;
            padding: 2.5rem;
            background: #f8f9fa;
        }

        /* 卡片样式 */
        .card {
            background-color: #ffffff;
            border-radius: 1.5rem;
            padding: 1.8rem;
            border: 1px solid #e0e0e0;
            box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08);
            transition: all 0.3s ease;
            display: flex;
            flex-direction: column;
        }

        .card:hover {
            transform: translateY(-6px);
            box-shadow: 0 12px 28px rgba(0, 0, 0, 0.12);
        }

        .card h2 {
            font-size: 1.5rem;
            font-weight: 600;
            color: #1a73e8;
            margin-bottom: 1.5rem;
            padding-bottom: 0.5rem;
            border-bottom: 1px solid #eee;
        }

        /* 传感器行样式 */
        .sensor-row {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin: 1.2rem 0;
            padding: 0.6rem 1rem;
            border-radius: 1rem;
            transition: background-color 0.3s;
        }

        .sensor-row:hover {
            background-color: #f5f7fa;
        }

        .label {
            font-weight: 500;
            color: #555;
            font-size: 1rem;
        }

        .value {
            font-size: 1.15rem;
            color: #1a73e8;
            font-weight: 600;
        }

        /* 状态标签样式 */
        .status-tag {
            padding: 0.4rem 0.8rem;
            border-radius: 0.5rem;
            font-size: 0.85rem;
            font-weight: 500;
            min-width: 60px;
            text-align: center;
        }

        .low { 
            background-color: #e8f5e9; 
            color: #2e7d32; 
        }

        .medium { 
            background-color: #fff3cd; 
            color: #856404; 
        }

        .high { 
            background-color: #f8d7da; 
            color: #721c24; 
        }

        /* 开关样式 */
        .switch {
            width: 50px;
            height: 24px;
            background: #ccc;
            border-radius: 30px;
            position: relative;
            cursor: pointer;
            transition: background-color 0.3s;
        }

        .switch::after {
            content: '';
            position: absolute;
            top: 3px;
            left: 3px;
            width: 18px;
            height: 18px;
            background: white;
            border-radius: 50%;
            transition: all 0.3s ease;
        }

        .switch.on {
            background-color: #4caf50;
        }

        .switch.on::after {
            left: 29px;
        }

        /* 功能卡片样式 */
        .action-card .action-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 1.5rem;
            margin-top: 1rem;
        }

        .action-item {
            background: #f8f9fa;
            border-radius: 1.2rem;
            padding: 1.5rem;
            text-align: center;
            cursor: pointer;
            transition: all 0.3s ease;
            border: 1px solid #eee;
            position: relative;
            overflow: hidden;
        }

        .action-item:hover {
            transform: translateY(-8px);
            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
        }

        /* 图标容器 */
        .icon-wrapper {
            width: 60px;
            height: 60px;
            border-radius: 1.5rem;
            margin: 0 auto 1rem;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.3s ease;
        }

        .action-item:hover .icon-wrapper {
            transform: scale(1.1) rotate(10deg);
        }

        /* 图标样式 */
        .action-icon {
            width: 30px;
            height: 30px;
        }

        /* 描述文本 */
        .description {
            font-size: 0.9rem;
            color: #666;
            margin: 0.5rem 0;
        }

        /* 分类标签 */
        .chip {
            display: inline-block;
            padding: 0.25rem 0.75rem;
            border-radius: 1rem;
            font-size: 0.75rem;
            font-weight: 500;
            margin-top: 0.5rem;
            background-color: #e8f5e9;
            color: #2e7d32;
        }

        .chip-green {
            background-color: #ccf2d1;
            color: #27803d;
        }

        .chip-yellow {
            background-color: #fff3cd;
            color: #856404;
        }

        /* 悬停特效 */
        .action-item::after {
            content: '';
            position: absolute;
            top: -50%;
            left: -50%;
            width: 200%;
            height: 200%;
            background: radial-gradient(circle at center, rgba(26, 115, 232, 0.05) 0%, transparent 70%);
            transform: rotate(45deg);
            opacity: 0;
            transition: all 0.5s ease;
        }

        .action-item:hover::after {
            opacity: 1;
        }

        /* 新增图表样式 */
        .chart-container {
            position: relative;
            height: 300px;
            margin-top: 2rem;
        }
        .dual-charts {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 2rem;
        }

        .chart-card {
            padding: 1.5rem;
            background-color: #f8f9fa;
            border-radius: 1.5rem;
            box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08);
            transition: all 0.3s ease;
        }
        
        .chart-card:hover {
            transform: translateY(-6px);
            box-shadow: 0 12px 28px rgba(0, 0, 0, 0.12);
        }
        
        .chart-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 1rem;
        }
        
        .time-range-btns {
            display: flex;
            gap: 0.5rem;
        }
        
        .time-range-btn {
            padding: 0.3rem 0.8rem;
            border-radius: 0.5rem;
            background: #e3f2fd;
            color: #1a73e8;
            font-size: 0.85rem;
            cursor: pointer;
            transition: all 0.3s ease;
        }
        
        .time-range-btn.active {
            background: #1a73e8;
            color: white;
        }

                /* AI悬浮窗口样式 */
        .ai-toggle {
            position: fixed;
            right: 2rem;
            bottom: 2rem;
            width: 56px;
            height: 56px;
            background: white;
            border-radius: 50%;
            box-shadow: 0 4px 20px rgba(0,0,0,0.2);
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            z-index: 1000;
            transition: transform 0.2s;
        }

        .ai-toggle:hover {
            transform: scale(1.1);
        }

        .ai-dialog {
            position: fixed;
            right: 2rem;
            bottom: 6rem;
            width: 400px; 
            max-width: 900px;           /* 设置最大宽度限制 */
            height: 600px;
            background: white;
            border-radius: 1rem;
            box-shadow: 0 8px 30px rgba(0,0,0,0.2);
            display: flex;
            flex-direction: column;
            z-index: 999;
            display: none;
            overflow: hidden;
            animation: slideIn 0.3s ease forwards;
        }
        /* 拖拽手柄样式 */
        .resize-handle {
            position: absolute;
            left: 4px;      /* 改为左上角 */
            top: 4px;
            width: 16px;
            height: 16px;
            background: #ddd;
            border-radius: 2px;
            cursor: nwse-resize;
            z-index: 10;
        }

        /* 鼠标悬停时显示更明显的拖拽图标 */
        .resize-handle:hover {
            background: #1a73e8;
        }

        /* 双箭头样式（可选） */
        .resize-handle::before {
            content: '';
            position: absolute;
            width: 100%;
            height: 100%;
            background: #1a73e8;
            border-radius: 2px;
            transform: rotate(45deg);
            opacity: 0.8;
        }

        /* 鼠标悬停时增强反馈 */
        .resize-handle:hover::before {
            background: #4caf50;
            opacity: 1;
        }

        /* 添加过渡效果 */
        .ai-dialog.resizing {
            transition: none; /* 拖拽时禁用过渡 */
        }
        @keyframes slideIn {
            from { transform: translateY(20px); opacity: 0; }
            to { transform: translateY(0); opacity: 1; }
        }

        .ai-header {
            padding: 1rem;
            background: #1a73e8;
            color: white;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .close-btn {
            background: none;
            border: none;
            color: white;
            font-size: 1.5rem;
            cursor: pointer;
        }

        .ai-chatbox {
            flex: 1;
            padding: 1rem;
            overflow-y: auto;
            background: #f5f7fa;
        }

        .input-area {
            display: flex;
            padding: 0.5rem;
            border-top: 1px solid #ddd;
            background: white;
        }

        .input-area input {
            flex: 1;
            font-size: 1rem; 
            padding: 0.8rem;
            border: 1px solid #ccc;
            border-radius: 0.5rem;
            margin-right: 0.5rem;
        }

        .input-area button {
            background: #1a73e8;
            color: white;
            border: none;
            font-size: 1rem; 
            padding: 0.8rem 1.2rem;
            border-radius: 0.5rem;
            cursor: pointer;
        }

        .message {
            margin: 0.5rem 0;
            line-height: 1.5;
        }

        .user {
            color: #1a73e8;
            text-align: right;
        }

        .bot {
            color: #000000 !important; 
        }

        .markdown-content {
            margin-top: 4px;
            line-height: 1.6;
        }

        .markdown-content ul, .markdown-content ol {
            padding-left: 20px;
            margin: 8px 0;
        }

        .markdown-content a {
            color: #1a0dab;
            text-decoration: underline;
        }

        .markdown-content code {
            background-color: #f0f0f0;
            padding: 2px 4px;
            border-radius: 4px;
            font-family: monospace;
        }

        .avatar {
        display: inline-block;
        width: 24px;
        height: 24px;
        border-radius: 50%;
        margin-right: 8px;
        vertical-align: middle;
        }
        .ai-name {
            font-weight: 600;
            margin-right: 8px;
            vertical-align: middle;
            display: inline-block;
        }

        .bot-message {
            display: flex !important;
            align-items: start !important;
        }

        .message-content {
            flex: 1;
        }
        /* 提示框主容器 */
        .ai-hint {
            position: fixed;
            right: 2rem;
            bottom: 8rem; /* 在按钮上方 */
            background: #1a73e8;
            color: white;
            padding: 0.8rem 1.2rem;
            border-radius: 0.8rem;
            max-width: 200px;
            opacity: 0;
            pointer-events: none;
            z-index: 1001;
            animation: fadeInUp 0.5s ease forwards;
            animation-delay: 1s;
            transform: translateY(20px);
            display: none;
        }

        /* 提示内容 */
        .ai-hint-content {
            display: flex;
            justify-content: space-between;
            align-items: center;
            gap: 1rem;
            min-width: 120px;
        }

        /* 关闭按钮 */
        .ai-hint-close {
            background: none;
            border: none;
            color: white;
            font-size: 1.2rem;
            cursor: pointer;
            margin-left: 0.5rem;
        }

        /* 箭头 */
        .ai-hint-arrow {
            position: absolute;
            bottom: -8px;
            right: 24px; /* 改为 right，从右侧偏移 */
            left: auto;  /* 清除 left 影响 */
            border-width: 8px 8px 0;
            border-style: solid;
            border-color: #1a73e8 transparent transparent;
            content: "";
        }

        /* 动画效果 */
        @keyframes fadeInUp {
            from {
                opacity: 0;
                transform: translateY(20px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }

        /* 新增报警样式 */
        .alarm-banner {
        position: fixed;
        top: 0;
        left: 50%;
        transform: translateX(-50%);
        width: 400px;
        max-width: 90%;
        background: #d32f2f;
        color: white;
        padding: 1rem 1.5rem;
        border-radius: 0 0 1rem 1rem;
        display: none; /* ✅ 默认隐藏 */
        align-items: center;
        z-index: 1000;
        box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
        opacity: 0;
        pointer-events: none;
        transition: all 0.5s ease;
        animation: none;
    }


    .alarm-banner.active {
        display: flex; /* ✅ 显示时恢复布局 */
        opacity: 1;
        pointer-events: auto;
        animation: flash 2s infinite;
    }
        
        .alarm-icon {
            margin-right: 1rem;
            
        }
        
        .alarm-text {
            flex: 1;
            font-size: 1.1rem;
            font-weight: bold;
        }
        
        .alarm-close {
            background: none;
            border: none;
            color: white;
            font-size: 1.5rem;
            cursor: pointer;
            margin-left: 1rem;
            display: none;
        }
        
        .alarm-banner.active .alarm-close {
            display: block;
        }
        
        @keyframes flash {
            0%, 100% { 
                opacity: 1; 
                transform: translateX(-50%) scale(1); 
            }
            50% { 
                opacity: 0.8; 
                transform: translateX(-50%) scale(1.02); 
            }
        }

        .analyze-btn {
            background: #fbbc05;
            color: #333;
            border: none;
            font-size: 1rem;
            padding: 0.8rem 1.2rem;
            border-radius: 0.5rem;
            cursor: pointer;
            margin-left: 0.5rem;
            transition: all 0.3s ease;
        }

        .analyze-btn:hover {
            background: #e8aa00;
            transform: translateY(-2px);
        }

    </style>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <!-- Marked: Markdown 解析器 -->
    <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
    <!-- DOMPurify: HTML 安全清理 -->
    <script src="https://cdn.jsdelivr.net/npm/dompurify@2.3.2/dist/purify.min.js"></script>
</head>
<body>
    <div class="container">
        <!-- 报警横幅 -->
        <div class="alarm-banner" id="alarmBanner">
            <div class="alarm-icon">
                
            </div>
            <div class="alarm-text" id="alarmText"></div>
            <button class="alarm-close" onclick="clearAlarm()">×</button>
        </div>
        <!-- 头部 -->
        <div class="header">
            <h1>记忆守护墙面系统</h1>
            <p>专为认知障碍患者设计的智能关怀平台</p>
        </div>

        <!-- 仪表盘 -->
        <div class="dashboard">
            <!-- 环境监测 -->
            <div class="card">
                <h2>环境监测</h2>
                <div class="sensor-row">
                    <div class="label">温度</div>
                    <div class="value" id="temperature">31.5°C</div>
                </div>
                <div class="sensor-row">
                    <div class="label">湿度</div>
                    <div class="value" id="humidity">0%</div>
                </div>
                <div class="sensor-row">
                    <div class="label">烟雾浓度</div>
                    <div class="status-tag low" id="smokeLevel">低</div>
                </div>
                <div class="sensor-row">
                    <div class="label">加湿器状态</div>
                    <div class="switch" id="humidifierSwitch" onclick="toggleDevice('humidifier')"></div>
                </div>
                <div class="sensor-row">
                    <div class="label">灯光状态</div>
                    <div class="switch" id="lightSwitch" onclick="toggleDevice('light')"></div>
                </div>
            </div>

            <!-- 人体状态 -->
            <div class="card">
                <h2>人体状态</h2>
                <div class="sensor-row">
                    <div class="label">人体存在</div>
                    <div class="switch" id="presenceSwitch"></div>
                </div>
                <div class="sensor-row">
                    <div class="label">体动特征</div>
                    <div class="value" id="movement">0</div>
                </div>
                <div class="sensor-row">
                    <div class="label">呼吸强度</div>
                    <div class="value" id="breathing">0 次/分</div>
                </div>
                <div class="sensor-row">
                    <div class="label">心率</div>
                    <div class="value" id="heartRate">0 BPM</div>
                </div>
            </div>

            <!-- 系统功能 -->
            <!-- 系统功能卡片 -->
            <div class="card action-card">
                    <h2>核心功能</h2>
                    <div class="action-grid">
                        <div class="action-item" onclick="window.location.href='reminder.html'">
                            <div class="icon-wrapper bg-blue-100">
                                <svg class="action-icon" viewBox="0 0 24 24" fill="none" stroke="#1a73e8" stroke-width="2">
                                    <circle cx="12" cy="12" r="10"></circle>
                                    <path d="M12 6v6l4 2"></path>
                                </svg>
                            </div>
                            <h3>提醒管理</h3>
                            <p class="description">设置服药、活动等日常提醒</p>
                            <div class="chip">智能提醒</div>
                        </div>

                        <div class="action-item" onclick="window.location.href='question.html'">
                            <div class="icon-wrapper bg-green-100">
                                <svg class="action-icon" viewBox="0 0 24 24" fill="none" stroke="#34a853" stroke-width="2">
                                    <path d="M9.09 9a3 3 0 015.83 1c0 2-3 3-3 3"></path>
                                    <circle cx="12" cy="12" r="10"></circle>
                                </svg>
                            </div>
                            <h3>题目管理</h3>
                            <p class="description">配置认知训练题目库</p>
                            <div class="chip chip-green">记忆训练</div>
                        </div>

                        <div class="action-item" onclick="window.location.href='upload.html'">
                            <div class="icon-wrapper bg-yellow-100">
                                <svg class="action-icon" viewBox="0 0 24 24" fill="none" stroke="#fbbc05" stroke-width="2">
                                    <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon>
                                </svg>
                            </div>
                            <h3>视频上传</h3>
                            <p class="description">上传定制化安抚视频</p>
                            <div class="chip chip-yellow">情感关怀</div>
                        </div>
                    </div>
                </div>
        </div>

        <!-- 环境监测图表 -->
        <div class="card chart-card">
            <div class="chart-header">
                <h2>环境监测数据</h2>
                <div class="time-range-btns">
                    <div class="time-range-btn" onclick="loadChartData('24h', event)">24小时</div>
                    <div class="time-range-btn" onclick="loadChartData('7d', event)">7天</div>
                    <div class="time-range-btn" onclick="loadChartData('30d', event)">30天</div>
                </div>
            </div>
            <div class="chart-container env-chart">
                <canvas id="envChart"></canvas> <!-- 添加画布 -->
            </div> 
        </div>  
        
        <!-- 环境监测图表 -->
        <div class="card chart-card">
            <div class="chart-header">
                <h2>人体状态数据</h2>
                <div class="time-range-btns">
                    <div class="time-range-btn" onclick="loadChartData('24h', event)">24小时</div>
                    <div class="time-range-btn" onclick="loadChartData('7d', event)">7天</div>
                    <div class="time-range-btn" onclick="loadChartData('30d', event)">30天</div>
                </div>
            </div>
            <div class="chart-container human-chart">
                <canvas id="humanChart"></canvas> <!-- 添加画布 -->
            </div> 
        </div> 

    </div>

    <script>
        // 替换为你的服务器IP
        const SERVER_IP = "47.109.75.129";

        // WebSocket 实时数据推送
        const ws = new WebSocket(`ws://${SERVER_IP}:3000`);

        ws.onmessage = (event) => {
            try {
                const data = JSON.parse(event.data);

                // 处理报警信息
                // ✅ 新增：检测手动报警来源
                if (data.alarm && data.source === 'device') {
                    manualAlarmActive = true; // 强制标记为手动报警
                    triggerAlarm(data.alarm);
                    activeAlarm = data.alarm;
                    return; // 直接返回，避免被自动逻辑干扰
                }
                // ✅ 优先处理手动报警标志
                if (manualAlarmActive) {
                    // 手动报警期间忽略自动报警
                    updateUI(data);
                    updateSensorChart(data); // 新增图表更新
                    return;
                }
                // ✅ 处理自动报警逻辑
                if (data.alarm && data.alarm !== '无') {
                    if (data.alarm !== activeAlarm) {
                        triggerAlarm(data.alarm);
                        activeAlarm = data.alarm;
                    }
                } else if (!manualAlarmActive) {
                    // 仅当非手动报警时清除
                    clearAlarm();
                    activeAlarm = null;
                }
                updateUI(data);
                updateSensorChart(data); // 新增图表更新
            } catch (error) {
                console.error("数据解析失败:", error);
            }
        };

        ws.onerror = (error) => {
            console.error("WebSocket Error:", error);
        };

        ws.onclose = () => {
            console.log("WebSocket 断开，尝试重连...");
            setTimeout(() => location.reload(), 5000); // 自动重连
        };
        
        // 新增全局变量
        let activeAlarm = null;
        let manualAlarmActive = false; // 区分手动和自动报警
        let closedAlarms = new Set();
        // 触发报警函数
        // 触发报警函数（新增文本校验）
        function triggerAlarm(message) {
            if (!manualAlarmActive) return; // 仅允许手动激活时更新
            console.log("触发报警", { message, manualAlarmActive }); // 调试日志
            
            const banner = document.getElementById('alarmBanner');
            const text = document.getElementById('alarmText');
            if (!message || message === '无') return;
            text.textContent = message;
            banner.classList.add('active');
            
            if (navigator.vibrate) navigator.vibrate([200, 100, 200]);

            // 记录报警ID（用于后续屏蔽）
            closedAlarms.add(message);
            
            setTimeout(() => {
                if (!manualClosed) {
                    _clearManualAlarm(); // 使用专用清除函数
                }
            }, 10000);
        }

        // 新增手动清除函数
        function _clearManualAlarm() {
            manualClosed = false;
            manualAlarmActive = false; // 更新标志位
            document.getElementById('alarmBanner').classList.remove('active');
            document.getElementById('alarmText').textContent = '';
        }
        // 在手动触发报警时调用
        function manualTriggerAlarm(message) {
            manualAlarmActive = true;
            triggerAlarm(message);

            // 可选：通过 localStorage 持久化（防刷新）
            localStorage.setItem('manualAlarm', JSON.stringify({
                message,
                timestamp: Date.now(),
                expired: false
            }));
        }

        // 清除报警函数（重置文本内容）
        function _clearAlarm() {
            manualClosed = false;
            const banner = document.getElementById('alarmBanner');
            const text = document.getElementById('alarmText');
            
            banner.classList.remove('active');
            text.textContent = ''; // 清空文本
        }

        // 手动关闭报警
        window.clearAlarm = function() {
            manualClosed = true;
            manualAlarmActive = false;
            localStorage.removeItem('manualAlarm'); // 清除本地存储
            _clearAlarm();
        };

        // 图表实时更新函数
        function updateSensorChart(data) {

            // 获取当前时间戳（格式化为HH:mm）
            const now = new Date();
            const timestamp = `${now.getHours()}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`;
            
            // 环境数据
            envChart.data.labels.push(now);
            envChart.data.datasets[0].data.push(data.temperature);
            envChart.data.datasets[1].data.push(data.humidity);
            
            // 人体数据
            humanChart.data.labels.push(now);
            humanChart.data.datasets[0].data.push(data.movement);
            humanChart.data.datasets[1].data.push(data.breathing);
            humanChart.data.datasets[2].data.push(data.heart_rate);

            // 限制最大数据点数量（保留最近50个点）
            const MAX_POINTS = 50;
            if (envChart.data.labels.length > MAX_POINTS) {
                envChart.data.labels.shift();
                envChart.data.datasets.forEach(dataset => dataset.data.shift());
            }
            if (humanChart.data.labels.length > MAX_POINTS) {
                humanChart.data.labels.shift();
                humanChart.data.datasets.forEach(dataset => dataset.data.shift());
            }

            const newMax = envChart.data.labels.length - 1; // 最新数据索引
            const newMin = Math.max(0, newMax - 30);        // 显示最近30个点
            // 自动滚动X轴（最新数据始终可见）
            envChart.options.scales.x.min = newMin;
            envChart.options.scales.x.max = newMax;
            humanChart.options.scales.x.min = newMin;
            humanChart.options.scales.x.max = newMax;
            
            envChart.update();
            humanChart.update();
        }
        // 更新UI
        function updateUI(data) {
            document.getElementById("temperature").textContent = `${data.temperature}°C`;
            document.getElementById("humidity").textContent = `${data.humidity}%`;
            document.getElementById("movement").textContent = data.movement;
            document.getElementById("breathing").textContent = `${data.breathing} `;
            document.getElementById("heartRate").textContent = `${data.heart_rate} BPM`;

            // 人体存在状态
            const presenceSwitch = document.getElementById("presenceSwitch");
            presenceSwitch.className = `switch ${data.presence ? 'on' : ''}`;


            // 烟雾浓度
            const smokeLevel = document.getElementById("smokeLevel");
            smokeLevel.className = `status-tag ${getSmokeClass(data.smoke_level)}`;
            smokeLevel.textContent = data.smoke_level;

            // 加湿器状态
            const humidifierSwitch = document.getElementById("humidifierSwitch");
            humidifierSwitch.className = `switch ${data.humidifier_status === '开启' ? 'on' : ''}`;

            // 灯光状态
            const lightSwitch = document.getElementById("lightSwitch");
            lightSwitch.className = `switch ${data.light_status === '开启' ? 'on' : ''}`;
        }

        // 烟雾等级样式
        function getSmokeClass(level) {
            switch(level) {
                case '低': return 'low';
                case '中': return 'medium';
                case '高': return 'high';
                default: return 'low';
            }
        }

        // 控制设备
        function toggleDevice(device) {
            const switchElement = document.getElementById(`${device}Switch`);
            const currentStatus = switchElement.classList.contains("on");
            const newStatus = currentStatus ? "off" : "on";
        
            // 立即更新按钮状态（优化体验）
            switchElement.className = `switch ${newStatus === 'on' ? 'on' : ''}`;
        
            // 发送控制指令
            fetch(`http://${SERVER_IP}:3000/api/control`, {
                method: "POST",
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify({ device, action: newStatus })
            })
            .then(res => res.json())
            .then(data => {
                console.log(`${device} 控制成功`);
            })
            .catch(err => {
                console.error(`控制失败:`, err);
                // 如果失败，恢复原状态
                switchElement.className = `switch ${currentStatus ? 'on' : ''}`;
                alert(`无法控制 ${device}`);
            });
        }

        // 初始化两个图表
        const envCtx = document.getElementById('envChart').getContext('2d');
        const humanCtx = document.getElementById('humanChart').getContext('2d');
        let envChart = null, humanChart = null;

        // 时间解析函数
        function parseTimestamp(timestamp, range) {
            const date = new Date(timestamp);
            // 确保分钟是字符串并补零
            const minutes = date.getMinutes().toString().padStart(2, '0');
            const hours = date.getHours().toString().padStart(2, '0');
            const seconds = date.getSeconds().toString().padStart(2, '0');
            
            if (range === '24h') {
                return `${hours}:${minutes}:${seconds}`;
            } else {
                return `${date.getMonth()+1}/${date.getDate()} ${hours}:${minutes}`;
            }
        }

        // 时间戳去重函数
        function deduplicateTimestamps(timestamps) {
            const seen = new Set();
            return timestamps.map((ts, i) => {
                let count = 1;
                while(seen.has(ts + (count > 1 ? `.${count}` : ''))) {
                    count++;
                }
                const uniqueTs = count > 1 ? `${ts}.${count}` : ts;
                seen.add(uniqueTs);
                return uniqueTs;
            });
        }

        function initChart() {
            // 销毁现有图表（如果存在）
            if (envChart) {
                envChart.destroy();
                envChart = null;
            }
            if (humanChart) {
                humanChart.destroy();
                humanChart = null;
            }
    
            envChart = new Chart(envCtx, {
                type: 'line',
                data : {
                    labels: [],
                    datasets: [
                        {
                            label: '温度 (°C)',
                            data: [],
                            borderColor: '#1a73e8',
                            backgroundColor: 'rgba(26, 115, 232, 0.1)',
                            tension: 0.3,
                            pointRadius: 3,
                            pointHoverRadius: 5,
                            fill: true
                        },
                        {
                            label: '湿度 (%)',
                            data: [],
                            borderColor: '#34a853',
                            backgroundColor: 'rgba(52, 168, 83, 0.1)',
                            tension: 0.3,
                            pointRadius: 3,
                            pointHoverRadius: 5,
                            fill: true
                        },
                    ]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    plugins: {
                        legend: {
                            labels: {
                                color: '#555',
                                font: {
                                    size: 12
                                }
                            }
                        },
                        tooltip: {
                            mode: 'index',
                            intersect: false,
                            backgroundColor: 'rgba(255, 255, 255, 0.95)',
                            titleColor: '#333',
                            bodyColor: '#555',
                            borderColor: '#ddd',
                            borderWidth: 1
                        }
                    },
                    interaction: {
                        mode: 'nearest',
                        axis: 'x',
                        intersect: false
                    },
                    scales: {
                        x: {
                            display: true,
                            title: {
                                display: true,
                                text: '时间',
                                color: '#555'
                            },
                            ticks: {
                                color: '#555',
                                font: {
                                    size: 10
                                },
                                source: 'auto', // 自动根据数据密度调整
                                maxRotation: 45, // 避免标签重叠
                                minRotation: 0,
                                
                                callback: function(value, index) {
                                const date = new Date(value);
                                return `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}:${date.getSeconds().toString().padStart(2, '0')}`;
                                }
                            },
                            grid: {
                                color: '#eee'
                            },
                            // ✅ 改用时间轴类型（关键）
                            type: 'category',
                            ticks: {
                                // ✅ 强制显示所有标签（关键）
                                autoSkip: false,
                                // ✅ 增加最大显示点数（原默认约20个点）
                                maxTicksLimit: 50
                            },
                            title: {
                                display: true,
                                text: '时间 (HH:mm:ss)'
                            },
                            // ✅ 自动滚动范围（可选）
                            min: 0,
                            max: 50 // 初始最大显示50个点
                        },
                        y: {
                            display: true,
                            title: {
                                display: true,
                                text: '数值',
                                color: '#555'
                            },
                            ticks: {
                                color: '#555',
                                font: {
                                    size: 10
                                }
                            },
                            grid: {
                                color: '#eee'
                            }
                        }
                    },
                    zoom: {
                        pan: {
                            enabled: true,
                            mode: 'x'
                        },
                        zoom: {
                            wheel: { enabled: true },
                            pinch: { enabled: true },
                            mode: 'x'
                        }
                    },
                    animation: {
                        duration: 1000,
                        easing: 'easeInOutQuart'
                    },
                    transitions: {
                        active: {
                            animation: {
                                duration: 500,
                                easing: 'easeOutQuart'
                            }
                        }
                    }
                }
            });

            humanChart = new Chart(humanCtx, {
                type: 'line',
                data : {
                    labels: [],
                    datasets: [
                        {
                            label: '体栋特征',
                            data: [],
                            borderColor: '#1a73e8',
                            backgroundColor: 'rgba(26, 115, 232, 0.1)',
                            tension: 0.3,
                            pointRadius: 3,
                            pointHoverRadius: 5,
                            fill: true
                        },
                        {
                            label: '呼吸特征',
                            data: [],
                            borderColor: '#34a853',
                            backgroundColor: 'rgba(52, 168, 83, 0.1)',
                            tension: 0.3,
                            pointRadius: 3,
                            pointHoverRadius: 5,
                            fill: true
                        },
                        {
                            label: '心率 (BPM)',
                            data: [],
                            borderColor: '#fbbc05',
                            backgroundColor: 'rgba(251, 188, 5, 0.1)',
                            tension: 0.3,
                            pointRadius: 3,
                            pointHoverRadius: 5,
                            fill: true
                        }
                    ]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    plugins: {
                        legend: {
                            labels: {
                                color: '#555',
                                font: {
                                    size: 12
                                }
                            }
                        },
                        tooltip: {
                            mode: 'index',
                            intersect: false,
                            backgroundColor: 'rgba(255, 255, 255, 0.95)',
                            titleColor: '#333',
                            bodyColor: '#555',
                            borderColor: '#ddd',
                            borderWidth: 1
                        }
                    },
                    interaction: {
                        mode: 'nearest',
                        axis: 'x',
                        intersect: false
                    },
                    scales: {
                        x: {
                            display: true,
                            title: {
                                display: true,
                                text: '时间',
                                color: '#555'
                            },
                            ticks: {
                                color: '#555',
                                font: {
                                    size: 10
                                },
                                source: 'auto', // 自动根据数据密度调整
                                maxRotation: 45, // 避免标签重叠
                                minRotation: 0,

                                callback: function(value, index) {
                                const date = new Date(value);
                                return `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}:${date.getSeconds().toString().padStart(2, '0')}`;
                                }
                            },
                            grid: {
                                color: '#eee'
                            },
                            // ✅ 改用时间轴类型（关键）
                            type: 'category',
                            ticks: {
                                // ✅ 强制显示所有标签（关键）
                                autoSkip: false,
                                // ✅ 增加最大显示点数（原默认约20个点）
                                maxTicksLimit: 50
                            },
                            title: {
                                display: true,
                                text: '时间 (HH:mm:ss)'
                            },
                            // ✅ 自动滚动范围（可选）
                            min: 0,
                            max: 50 // 初始最大显示50个点
                        },
                        y: {
                            display: true,
                            title: {
                                display: true,
                                text: '数值',
                                color: '#555'
                            },
                            ticks: {
                                color: '#555',
                                font: {
                                    size: 10
                                }
                            },
                            grid: {
                                color: '#eee'
                            }
                        }
                    },
                    zoom: {
                        pan: {
                            enabled: true,
                            mode: 'x'
                        },
                        zoom: {
                            wheel: { enabled: true },
                            pinch: { enabled: true },
                            mode: 'x'
                        }
                    },
                    animation: {
                        duration: 1000,
                        easing: 'easeInOutQuart'
                    },
                    transitions: {
                        active: {
                            animation: {
                                duration: 500,
                                easing: 'easeOutQuart'
                            }
                        }
                    }
                }
            });

        }
        // ✅ 新增：加载图表数据函数
        async function loadChartData(range = '24h', event) {
        try {
            // 安全处理事件对象
            if (event) {
            const target = event.target;
            if (target) {
                document.querySelectorAll('.time-range-btn').forEach(btn => btn.classList.remove('active'));
                target.classList.add('active');
            }
            }

            // 添加缓存破坏参数
            const cacheBuster = `&_=${Date.now()}`;
            const response = await fetch(`http://${SERVER_IP}:3000/api/sensor/history?range=${range}${cacheBuster}`);
            
            if (!response.ok) {
            throw new Error(`API请求失败: ${response.status}`);
            }
            
            const data = await response.json();

            // 强制排序确保时间顺序
            data.sort((a, b) => new Date(a.timestamp) - new Date(b.timestamp));
            // 只取最新的50条数据
            //data = data.slice(0, 50);
            
            // 处理时间戳格式
            const timestamps = data.map(item => {
                return parseTimestamp(item.timestamp, range);
            });
            // ✅ 调用 deduplicateTimestamps 处理重复时间戳
            const uniqueTimestamps = deduplicateTimestamps(timestamps);
            
            if (envChart || humanChart) {
                // 销毁并重建图表（避免重用错误）
                initChart();
                
                // 设置新数据
                
                envChart.data.labels = timestamps;
                envChart.data.datasets[0].data = data.map(item => item.temperature);
                envChart.data.datasets[1].data = data.map(item => item.humidity);
                humanChart.data.labels = timestamps;
                humanChart.data.datasets[0].data = data.map(item => item.movement);
                humanChart.data.datasets[1].data = data.map(item => item.breathing);
                humanChart.data.datasets[2].data = data.map(item => item.heart_rate);
            
                // 更新图表
                envChart.update();
                humanChart.update();
            }

        } catch (error) {
            console.error("获取历史数据失败:", error);
            alert("无法加载历史数据: " + error.message);
            }
        }

    // ✅ 新增：页面加载时初始化
    document.addEventListener('DOMContentLoaded', () => {
        initChart();
        loadChartData('24h'); // 移除event参数
        startAutoRefresh();

        const dialog = document.getElementById('aiDialog');
        const handle = document.getElementById('resizeHandle');
        
        // 从localStorage加载上次保存的尺寸
        loadDialogSize(dialog);
        
        // 拖拽逻辑
        let isResizing = false;
        let startX, startY, startWidth, startHeight;

        handle.addEventListener('mousedown', (e) => {
            isResizing = true;
            dialog.classList.add('resizing');
            startX = e.clientX;
            startY = e.clientY;
            startWidth = dialog.offsetWidth;
            startHeight = dialog.offsetHeight;
            e.preventDefault();
        });

        document.addEventListener('mousemove', (e) => {
            if (!isResizing) return;
            
            // 从左上角调整方向
            const newWidth = startWidth - (e.clientX - startX);
            const newHeight = startHeight - (e.clientY - startY);
            
            // 设置最小尺寸限制
            if (newWidth >= 300 && newHeight >= 400) {
                dialog.style.width = `${newWidth}px`;
                dialog.style.height = `${newHeight}px`;
            }
        });

        document.addEventListener('mouseup', () => {
            if (isResizing) {
                saveDialogSize(dialog);
                dialog.classList.remove('resizing');
            }
            isResizing = false;
        });

        const saved = localStorage.getItem('manualAlarm');
        if (saved) {
            const alarm = JSON.parse(saved);
            if (!alarm.expired) {
                manualAlarmActive = true;
                triggerAlarm(alarm.message);
            }
        }
        
    });

    // 修改定时刷新函数
    function startAutoRefresh() {
    setInterval(() => {
        const activeBtn = document.querySelector('.time-range-btn.active');
        const range = activeBtn ? 
            (activeBtn.textContent.includes('24') ? '24h' : 
             activeBtn.textContent.includes('7') ? '7d' : '30d') 
            : '24h';
            
        loadChartData(range);
        }, 30000); // 30秒刷新一次
    }

    // 新增独立刷新函数（不改变图表实例）
    async function refreshChartData(range = '24h') {
        try {
            const response = await fetch(`http://${SERVER_IP}:3000/api/sensor/history?range=${range}`);
            if (!response.ok) throw new Error('数据刷新失败');
            
            const data = await response.json();
            const timestamps = data.map(item => {
                const date = new Date(item.timestamp);
                return range === '24h' ? 
                    `${date.getHours()}:${date.getMinutes().padStart(2, '0')}` : 
                    `${date.getMonth()+1}/${date.getDate()} ${date.getHours()}:${date.getMinutes().padStart(2, '0')}`;
            });

            // 直接更新数据（不销毁图表）
            envChart.data.labels = timestamps;
            envChart.data.datasets[0].data = data.map(item => item.temperature);
            envChart.data.datasets[1].data = data.map(item => item.humidity);
            humanChart.data.labels = timestamps;
            humanChart.data.datasets[0].data = data.map(item => item.movement);
            humanChart.data.datasets[1].data = data.map(item => item.breathing);
            humanChart.data.datasets[2].data = data.map(item => item.heart_rate);
            
            // 重置X轴范围以显示完整数据
            
            envChart.options.scales.x.min = 0;
            envChart.options.scales.x.max = timestamps.length;
            humanChart.options.scales.x.min = 0;
            humanChart.options.scales.x.max = timestamps.length;
            
            
            envChart.update();
            humanChart.update();
        } catch (error) {
            console.error("图表刷新失败:", error);
        }
    }


    // 保持原有API调用逻辑不变
    let currentSessionId = null;
    let aiChatbox = null;

    function initAI() {
        aiChatbox = document.getElementById('aiChatbox');
    }

    function toggleAI() {
        const dialog = document.getElementById('aiDialog');
        dialog.style.display = dialog.style.display === 'flex' ? 'none' : 'flex';
    }

    function handleKeyPress(e) {
        if (e.key === 'Enter') sendMessage();
    }

    async function sendMessage() {
        const input = document.getElementById('aiInput');
        const message = input.value.trim();
        if (!message) return;
        
        addMessage('您', message);
        const aiAvatar = `
        <svg viewBox="0 0 24 24" width="20" height="20" fill="#1a73e8" style="margin-right: 8px; vertical-align: middle;">
            <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15h-2v-6h2v6zm1-8c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm7 8h-2V9h2v6z"/>
        </svg>
        `;
        
        try {
            const API_BASE_URL = 'http://47.109.75.129:3000';
            const response = await fetch(`${API_BASE_URL}/api/chat`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    message,
                    sessionId: currentSessionId
                })
            });
            
            if (!response.ok) throw new Error('Network response was not ok');
            
            const reader = response.body.getReader();
            const decoder = new TextDecoder("utf-8");
            let aiResponseElement = null;
            let accumulatedText = '';
            let currentSessionIdFromStream = null;
            
            while (true) {
                const { done, value } = await reader.read();
                if (done) break;
                
                const chunk = decoder.decode(value, { stream: true });
                const lines = chunk.split('\n');
                
                for (const line of lines) {
                    if (line.startsWith('data:')) {
                        const dataStr = line.slice(5).trim();
                        if (dataStr) {
                            try {
                                const parsed = JSON.parse(dataStr);
                                const text = parsed.output?.text || '';
                                currentSessionIdFromStream = parsed.output?.session_id || currentSessionIdFromStream;
                                accumulatedText += text;
                                
                                if (!aiResponseElement) {
                                    aiResponseElement = document.createElement('div');
                                    aiResponseElement.className = 'message';
                                    aiResponseElement.innerHTML = `
                                        <div class="bot-message">
                                        ${aiAvatar}
                                        <div class="message-content">
                                            <span class="ai-name">小艺</span>
                                            <div class="markdown-content"></div>
                                        </div>
                                    </div>
                                    `;
                                    aiChatbox.appendChild(aiResponseElement);
                                }
                                
                                const dirtyHTML = marked.parse(accumulatedText);
                                const cleanHTML = DOMPurify.sanitize(dirtyHTML);
                                aiResponseElement.querySelector('.markdown-content').innerHTML = cleanHTML;
                                aiChatbox.scrollTop = aiChatbox.scrollHeight;
                            } catch (e) {
                                console.error('JSON parse error:', e);
                            }
                        }
                    }
                }
            }
            
            currentSessionId = currentSessionIdFromStream;
        } catch (error) {
            addMessage('系统', '通信失败：' + error.message);
        }
        
        input.value = '';
    }

    function addMessage(sender, text) {
        const chatbox = document.getElementById('aiChatbox');
        const msg = document.createElement('div');
        msg.className = 'message';
        
        const dirtyHTML = marked.parse(text);
        const cleanHTML = DOMPurify.sanitize(dirtyHTML);
        
        // 使用按钮的SVG图标作为头像
        const aiAvatar = `
        <svg viewBox="0 0 24 24" width="20" height="20" fill="#1a73e8" style="margin-right: 8px; vertical-align: middle;">
            <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15h-2v-6h2v6zm1-8c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm7 8h-2V9h2v6z"/>
        </svg>
        `;

        // 区分用户和AI消息样式
        if (sender === '您') {
            // 用户消息右对齐
            msg.innerHTML = `
                <span class="user" style="text-align:right;display:block">
                    <div class="markdown-content">${cleanHTML}</div>
                    <small style="color:#666;margin-top:4px;display:inline-block">您</small>
                </span>
            `;
        } else {
            // AI消息带头像和名称
            msg.innerHTML = `
                 <div class="bot-message">
                ${aiAvatar}
                <div class="message-content">
                    <span class="ai-name">小艺</span>
                    <div class="markdown-content">${cleanHTML}</div>
                </div>
            </div>
            `;
        }
        
        chatbox.appendChild(msg);
        chatbox.scrollTop = chatbox.scrollHeight;
    }

    // 初始化AI功能
    document.addEventListener('DOMContentLoaded', () => {
        initAI();
        // 添加点击事件监听
        document.getElementById('aiToggle').addEventListener('click', toggleAI);
    });

    // 初始化提示框
    document.addEventListener('DOMContentLoaded', () => {
        // 初始化AI功能
        initAI();
        
        // 添加点击事件监听
        document.getElementById('aiToggle').addEventListener('click', toggleAI);
        
        // 显示提示框（仅首次访问）
        showHintIfFirstTime();
    });

    // 显示提示框
    function showHintIfFirstTime() {
        const hint = document.getElementById('aiHint');
        hint.style.display = 'block';
        
        setTimeout(() => {
            closeHint();
        }, 5000);
    }

    // 关闭提示框
    function closeHint() {
        const hint = document.getElementById('aiHint');
        hint.style.opacity = '0';
        hint.style.transform = 'translateY(20px)';
        
        // 延迟移除元素以保证动画完成
        setTimeout(() => {
            hint.style.display = 'none';
        }, 300);
        
        // 标记为已查看
        localStorage.setItem('aiHintShown', 'true');
    }

    // 保存尺寸到localStorage
    function saveDialogSize(dialog) {
        localStorage.setItem('aiDialogWidth', dialog.offsetWidth);
        localStorage.setItem('aiDialogHeight', dialog.offsetHeight);
    }

    // 从localStorage加载尺寸
    function loadDialogSize(dialog) {
        const width = localStorage.getItem('aiDialogWidth');
        const height = localStorage.getItem('aiDialogHeight');
        
        if (width && height) {
            dialog.style.width = `${parseInt(width)}px`;
            dialog.style.height = `${parseInt(height)}px`;
        }
    }

    // 分析健康数据（默认分析24小时数据）
    async function analyzeHealthData(range = '24h') {
        try {
            // 添加缓存破坏参数防止浏览器缓存
            const cacheBuster = `&_=${Date.now()}`;
            const response = await fetch(`http://${SERVER_IP}:3000/api/sensor/history?range=${range}${cacheBuster}`);
            
            if (!response.ok) {
                throw new Error(`API请求失败: ${response.status}`);
            }
            
            const data = await response.json();
            
            // 检查是否有足够的数据
            if (data.length === 0) {
                addMessage('系统', '没有足够的历史数据可供分析，请稍后再试');
                return;
            }
            
            // 计算统计数据
            const stats = calculateHealthStats(data);
            
            // 生成分析请求文本
            const analysisRequest = generateAnalysisRequest(stats, range);
            
            // 显示"分析中..."提示，而不是发送的文本内容
            const loadingMessageId = addLoadingMessage();
            
            // 直接发送分析请求，不显示原始数据
            sendAnalysisRequest(analysisRequest, loadingMessageId);
            
        } catch (error) {
            console.error("健康数据分析失败:", error);
            addMessage('系统', '健康数据分析失败: ' + error.message);
        }
    }

    // 计算健康统计数据
    function calculateHealthStats(data) {
        const stats = {
            temperature: { values: [], avg: 0, min: Infinity, max: -Infinity },
            humidity: { values: [], avg: 0, min: Infinity, max: -Infinity },
            smoke_level: { lowCount: 0, mediumCount: 0, highCount: 0 },
            presence: { presentCount: 0, totalCount: data.length },
            movement: { values: [], avg: 0, min: Infinity, max: -Infinity },
            breathing: { values: [], avg: 0, min: Infinity, max: -Infinity },
            heart_rate: { values: [], avg: 0, min: Infinity, max: -Infinity, highCount: 0 }
        };
        
        // 遍历数据计算统计值
        data.forEach(item => {
            // 温度
            stats.temperature.values.push(item.temperature);
            stats.temperature.avg += item.temperature;
            stats.temperature.min = Math.min(stats.temperature.min, item.temperature);
            stats.temperature.max = Math.max(stats.temperature.max, item.temperature);
            
            // 湿度
            stats.humidity.values.push(item.humidity);
            stats.humidity.avg += item.humidity;
            stats.humidity.min = Math.min(stats.humidity.min, item.humidity);
            stats.humidity.max = Math.max(stats.humidity.max, item.humidity);
            
            // 烟雾浓度
            if (item.smoke_level === '低') stats.smoke_level.lowCount++;
            else if (item.smoke_level === '中') stats.smoke_level.mediumCount++;
            else if (item.smoke_level === '高') stats.smoke_level.highCount++;
            
            // 人体存在
            if (item.presence) stats.presence.presentCount++;
            
            // 体动特征
            stats.movement.values.push(item.movement);
            stats.movement.avg += item.movement;
            stats.movement.min = Math.min(stats.movement.min, item.movement);
            stats.movement.max = Math.max(stats.movement.max, item.movement);
            
            // 呼吸强度
            stats.breathing.values.push(item.breathing);
            stats.breathing.avg += item.breathing;
            stats.breathing.min = Math.min(stats.breathing.min, item.breathing);
            stats.breathing.max = Math.max(stats.breathing.max, item.breathing);
            
            // 心率
            stats.heart_rate.values.push(item.heart_rate);
            stats.heart_rate.avg += item.heart_rate;
            stats.heart_rate.min = Math.min(stats.heart_rate.min, item.heart_rate);
            stats.heart_rate.max = Math.max(stats.heart_rate.max, item.heart_rate);
            if (item.heart_rate > 100) stats.heart_rate.highCount++;
        });
        
        // 计算平均值
        const count = data.length;
        stats.temperature.avg /= count;
        stats.humidity.avg /= count;
        stats.movement.avg /= count;
        stats.breathing.avg /= count;
        stats.heart_rate.avg /= count;
        
        return stats;
    }

    // 生成AI分析请求文本
    function generateAnalysisRequest(stats, range) {
        // 将时间范围转换为中文描述
        let rangeDesc = '';
        switch(range) {
            case '24h': rangeDesc = '过去24小时'; break;
            case '7d': rangeDesc = '过去7天'; break;
            case '30d': rangeDesc = '过去30天'; break;
            default: rangeDesc = `过去${range}`;
        }
        
        // 计算存在比例
        const presencePercentage = (stats.presence.presentCount / stats.presence.totalCount * 100).toFixed(1);
        
        // 生成分析请求文本
        let request = `# 老人健康数据分析请求（${rangeDesc}）\n\n`;
        
        // 环境数据
        request += `## 1. 环境数据\n`;
        request += `- **温度**：平均 ${stats.temperature.avg.toFixed(1)}°C，范围 ${stats.temperature.min.toFixed(1)}°C - ${stats.temperature.max.toFixed(1)}°C\n`;
        request += `- **湿度**：平均 ${stats.humidity.avg.toFixed(1)}%，范围 ${stats.humidity.min.toFixed(1)}% - ${stats.humidity.max.toFixed(1)}%\n`;
        
        // 烟雾浓度
        const totalSmoke = stats.smoke_level.lowCount + stats.smoke_level.mediumCount + stats.smoke_level.highCount;
        const lowSmokePercent = totalSmoke > 0 ? (stats.smoke_level.lowCount / totalSmoke * 100).toFixed(1) : 0;
        const mediumSmokePercent = totalSmoke > 0 ? (stats.smoke_level.mediumCount / totalSmoke * 100).toFixed(1) : 0;
        const highSmokePercent = totalSmoke > 0 ? (stats.smoke_level.highCount / totalSmoke * 100).toFixed(1) : 0;
        
        request += `- **烟雾浓度**：低 (${lowSmokePercent}%)，中 (${mediumSmokePercent}%)，高 (${highSmokePercent}%)\n\n`;
        
        // 人体状态数据
        request += `## 2. 人体状态数据\n`;
        request += `- **人体存在**：检测到存在 ${stats.presence.presentCount} 次（${presencePercentage}% 时间）\n`;
        request += `- **体动特征**：平均值 ${stats.movement.avg.toFixed(1)}，范围 ${stats.movement.min.toFixed(1)} - ${stats.movement.max.toFixed(1)}\n`;
        request += `- **呼吸强度**：平均 ${stats.breathing.avg.toFixed(1)} 次/分，范围 ${stats.breathing.min.toFixed(1)} - ${stats.breathing.max.toFixed(1)} 次/分\n`;
        request += `- **心率**：平均 ${stats.heart_rate.avg.toFixed(1)} BPM，范围 ${stats.heart_rate.min.toFixed(1)} - ${stats.heart_rate.max.toFixed(1)} BPM，有 ${stats.heart_rate.highCount} 次异常高于 100 BPM\n\n`;
        
        request += `## 3. 分析要求\n`;
        request += `- 请分析老人的健康状况趋势\n`;
        request += `- 指出可能的健康风险\n`;
        request += `- 提供针对性的健康建议\n`;
        request += `- 如有异常情况，请特别说明`;
        
        return request;
    }

    // 添加加载中消息
    function addLoadingMessage() {
        const chatbox = document.getElementById('aiChatbox');
        const msg = document.createElement('div');
        msg.className = 'message';
        msg.id = 'loading-message';
        
        const aiAvatar = `
        <svg viewBox="0 0 24 24" width="20" height="20" fill="#1a73e8" style="margin-right: 8px; vertical-align: middle;">
            <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15h-2v-6h2v6zm1-8c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm7 8h-2V9h2v6z"/>
        </svg>
        `;
        
        msg.innerHTML = `
            <div class="bot-message">
                ${aiAvatar}
                <div class="message-content">
                    <span class="ai-name">小艺</span>
                    <div class="markdown-content">正在分析老人健康数据，请稍候...</div>
                </div>
            </div>
        `;
        
        chatbox.appendChild(msg);
        chatbox.scrollTop = chatbox.scrollHeight;
        
        // 返回消息元素ID，用于后续更新
        return msg.id;
    }

    // 发送分析请求（不显示原始数据）
    async function sendAnalysisRequest(analysisRequest, loadingMessageId) {
        try {
            const API_BASE_URL = 'http://47.109.75.129:3000';
            const response = await fetch(`${API_BASE_URL}/api/chat`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    message: analysisRequest,
                    sessionId: currentSessionId
                })
            });
            
            if (!response.ok) throw new Error('Network response was not ok');
            
            const reader = response.body.getReader();
            const decoder = new TextDecoder("utf-8");
            let aiResponseElement = document.getElementById(loadingMessageId);
            if (!aiResponseElement) {
                // 如果加载消息已被移除（理论上不会发生），重新添加
                aiResponseElement = document.createElement('div');
                aiResponseElement.className = 'message';
                aiResponseElement.id = 'loading-message';
                aiChatbox.appendChild(aiResponseElement);
            }
            
            // 更新消息内容区域
            const contentDiv = aiResponseElement.querySelector('.markdown-content');
            let accumulatedText = '';
            let currentSessionIdFromStream = null;
            
            while (true) {
                const { done, value } = await reader.read();
                if (done) break;
                const chunk = decoder.decode(value, { stream: true });
                const lines = chunk.split('\n');
                for (const line of lines) {
                    if (line.startsWith('data:')) {
                        const dataStr = line.slice(5).trim();
                        if (dataStr) {
                            try {
                                const parsed = JSON.parse(dataStr);
                                const text = parsed.output?.text || '';
                                currentSessionIdFromStream = parsed.output?.session_id || currentSessionIdFromStream;
                                accumulatedText += text;
                                
                                // 更新"正在分析"消息为实际回复内容
                                const dirtyHTML = marked.parse(accumulatedText);
                                const cleanHTML = DOMPurify.sanitize(dirtyHTML);
                                contentDiv.innerHTML = cleanHTML;
                                aiChatbox.scrollTop = aiChatbox.scrollHeight;
                            } catch (e) {
                                console.error('JSON parse error:', e);
                            }
                        }
                    }
                }
            }
            
            currentSessionId = currentSessionIdFromStream;
            
        } catch (error) {
            // 如果出错，更新"正在分析"消息为错误信息
            const loadingMsg = document.getElementById(loadingMessageId);
            if (loadingMsg) {
                const contentDiv = loadingMsg.querySelector('.markdown-content');
                contentDiv.innerHTML = `分析失败: ${error.message}`;
            }
        }
    }

    </script>
</body>
<!-- AI悬浮按钮 -->
<div id="aiToggle" class="ai-toggle">
    <svg viewBox="0 0 24 24" width="24" height="24" fill="#1a73e8">
        <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15h-2v-6h2v6zm1-8c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm7 8h-2V9h2v6z"/>
    </svg>
</div>

<!-- AI对话框 -->
<div class="ai-dialog" id="aiDialog">
    <div class="ai-header">
        <span>AI助手</span>
        <button class="close-btn" onclick="toggleAI()">×</button>
    </div>
    <div class="ai-chatbox" id="aiChatbox"></div>
    <div class="input-area">
        <input type="text" id="aiInput" placeholder="输入消息..." onkeypress="handleKeyPress(event)">
        <button onclick="sendMessage()">发送</button>
        <button onclick="analyzeHealthData('24h')" class="analyze-btn">分析健康数据</button>
    </div>
    <!-- 新增：拖拽调整手柄 -->
    <div class="resize-handle" id="resizeHandle"></div>
</div>

<!-- 提示框结构 -->
<div id="aiHint" class="ai-hint">
    <div class="ai-hint-content">
        <p>点击按钮开始AI对话</p>
        <button class="ai-hint-close" onclick="closeHint()">×</button>
    </div>
    <div class="ai-hint-arrow"></div>
</div>
</html>